﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using WooCoo.Data;

namespace WooCoo.Extension
{
    public static class TypeExtension
    {
        #region 获取数据类型
        /// <summary>
        /// 获取数据类型
        /// </summary>
        /// <returns></returns>
        public static DbType GetDbType(this Type type)
        {
            var typeName = GetNullableType(type).Name;
            switch (typeName)
            {
                case "Byte[]":
                    return DbType.Binary;
                case "DateTime":
                    return DbType.DateTime;
                default:
                    return (DbType)Enum.Parse(typeof(DbType), typeName);
            }
        }

        public static Type GetNullableType(Type sourceType)
        {
            // Use Nullable.GetUnderlyingType() to remove the Nullable<T> wrapper if type is already nullable.
            var type = Nullable.GetUnderlyingType(sourceType);
            if (type == null)
                return sourceType;
            //if (type.IsValueType)
            //    return typeof(Nullable<>).MakeGenericType(type);
            //else
            return type;
        }
        #endregion
       
        #region 获取指定类型的属性,如果不存在则返回默认
        /// <summary>
        /// 获取指定类型的属性,如果不存在则返回默认
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="propertyInfo"></param>
        /// <returns></returns>
        internal static T GetCustomAttribute<T>(this PropertyInfo propertyInfo)
            where T : class
        {
            var customAttributes = propertyInfo.GetCustomAttributes(typeof(T), true);
            if (customAttributes.Length > 0)
            {
                return (T)customAttributes[0];
            }
            return null;
        }
        #endregion        
        /// <summary>
        /// Returns all static methods in the Queryable and Enumerable classes.
        /// </summary>
        internal static IEnumerable<MethodInfo> GetPublicStaticMethods(this Type type)
        {
            return type.GetMethods(BindingFlags.Static | BindingFlags.Public);
        }

        /// <summary>
        /// Gets a method on the specified type.
        /// </summary>
        /// <param name="type">Type on which to call this helper method.</param>
        /// <param name="name">Name of the method on the type.</param>
        /// <param name="isPublic">True if method should search only public methods, false if it should search only non-public methods.</param>
        /// <param name="isStatic">True if method should search only static methods, false if it should search only instance methods.</param>
        /// <returns>MethodInfo for the method with the specified characteristics if found, otherwise null.</returns>
        internal static MethodInfo GetMethod(this Type type, string name, bool isPublic, bool isStatic)
        {
            BindingFlags bindingFlags = BindingFlags.Default;
            bindingFlags |= isPublic ? BindingFlags.Public : BindingFlags.NonPublic;
            bindingFlags |= isStatic ? BindingFlags.Static : BindingFlags.Instance;
            return type.GetMethod(name, bindingFlags);
        }
    }
}
